package com.xbongbong.saas.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.service.PaasFormDataService;
import com.xbongbong.paas.service.dynamic.help.DynamicHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.customercommunicate.pojo.dto.DynamicListDTO;
import com.xbongbong.pro.customercommunicate.pojo.vo.CommunicateDynamicsListVO;
import com.xbongbong.pro.customercommunicate.pojo.vo.CustomerDynamicsVO;
import com.xbongbong.pro.dynamic.pojo.vo.DynamicFormDataDetailVO;
import com.xbongbong.pro.dynamic.pojo.vo.DynamicFormDataDetailVO;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.dto.FormDataDetailDTO;
import com.xbongbong.pro.formdata.pojo.vo.FormDataDetailVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.DynamicEntity;
import com.xbongbong.saas.domain.entity.competitor.SimpleDynamicEntity;
import com.xbongbong.saas.domain.entity.ext.CustomerCommunicateEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.CustomerCommunicateModel;
import com.xbongbong.saas.model.DynamicModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.model.SimpleDynamicModel;
import com.xbongbong.saas.service.SaasDynamicService;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

@Service("saasDynamicService")
public class DynamicServiceImpl implements SaasDynamicService {
    @Resource
    private DynamicModel dynamicModel;
    @Resource
    private UserModel userModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private PaasFormDataService paasFormDataService;
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private CustomerCommunicateModel customerCommunicateModel;
    @Resource
    private SimpleDynamicModel simpleDynamicModel;
    @Resource
    private DynamicHelp dynamicHelp;

    @Override
    public CommunicateDynamicsListVO getDynamicsList(DynamicListDTO dynamicListDTO) throws XbbException {
        String corpid = dynamicListDTO.getCorpid();
        Integer page = dynamicListDTO.getPage() == null ? 1 : dynamicListDTO.getPage();
        Integer pageSize = dynamicListDTO.getPageSize() == null ? 10 : dynamicListDTO.getPageSize();
        Integer businessType = dynamicListDTO.getBusinessType();
        Long parentId = dynamicListDTO.getParentId();
        // Long customerId = dynamicListDTO.getCustomerId();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        // if(Objects.nonNull(customerId)){
        //     // 机会和合同 会有customerId 走索引
        //     param.put("customerId", customerId);
        // }
        param.put(getQueryAttr(businessType), parentId);
        param.put(StringConstant.DEL, 0);
        param.put(StringConstant.ORDER_BY, "add_time desc");
        param.put("start", (page - 1) * pageSize);
        param.put("pageSize", pageSize);
        List<DynamicEntity> dynamicModelEntitys = dynamicModel.findEntitys(param);

        CommunicateDynamicsListVO communicateDynamicsListVO = new CommunicateDynamicsListVO();
        List<CustomerDynamicsVO> list = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(dynamicModelEntitys)) {
            for (DynamicEntity entity : dynamicModelEntitys) {
                CustomerDynamicsVO customerDynamicsVO = new CustomerDynamicsVO();
                customerDynamicsVO.setMemo(entity.getMemo());
                customerDynamicsVO.setCommunicateTime(entity.getAddTime());
                JSONObject communicateBusiness = new JSONObject();
                Long refId = entity.getRefId();

                if (Objects.equals(XbbRefTypeEnum.CALL_CENTER.getCode(), entity.getRefBusinessType())) {
                    JSONObject entityObj = new JSONObject();
                    Integer communicateBuisenssType = entity.getRefBusinessType();
                    entityObj.put("businessType", communicateBuisenssType);
                    communicateBusiness.put("entity", entityObj);
                    communicateBusiness.put("name", entity.getRefName());
                    customerDynamicsVO.setCommunicateBusiness(communicateBusiness);
                } else {
                    // 合理显示关联信息呢
                    if (Objects.nonNull(refId) && refId != 0L &&
                            !(Objects.equals(businessType, entity.getRefBusinessType()) && Objects.equals(parentId, refId))
                    ) {
                        // 方便前端跳详情
                        JSONObject entityObj = new JSONObject();
                        Integer communicateBuisenssType = entity.getRefBusinessType();
                        Integer businessType4Distributor = XbbRefTypeEnum.transferBusinessType4Distributor(communicateBuisenssType, dynamicListDTO.getDistributorMark());
                        entityObj.put("dataId", refId);
                        entityObj.put("businessType", communicateBuisenssType);
                        entityObj.put("saasMark", Objects.equals(communicateBuisenssType, 0) ? SaasMarkEnum.PAAS.getCode() : SaasMarkEnum.SAAS.getCode());
                        String businessName = "";
                        if (Objects.equals(communicateBuisenssType, 0)) {
                            businessName = I18nMessageUtil.getMessage(StringConstant.LINK_DATA);
                        } else {
                            businessName = XbbRefTypeEnum.getByCode(businessType4Distributor).getName();
                        }
                        communicateBusiness.put("entity", entityObj);
                        communicateBusiness.put("businessName", businessName);
                        // 重新查询一下关联对象名称，防止改名
                        communicateBusiness.put("name", StringUtil.isNotEmpty(entity.getRefName()) ? dynamicHelp.getRealRefName(corpid,refId,communicateBuisenssType,entity.getRefName()) : "--");
                        customerDynamicsVO.setCommunicateBusiness(communicateBusiness);
                    }
                }
                customerDynamicsVO.setAddTime(entity.getAddTime());

                list.add(customerDynamicsVO);
            }
        }
        // 设置分页数据
        param.remove("start");
        param.remove("pageSize");
        param.remove(StringConstant.ORDER_BY);
        PageHelper pageHelper = PageHelperUtil.initPageHelper(dynamicModel.getEntitysCount(param), page, pageSize, pageSize);
        communicateDynamicsListVO.setList(list);
        communicateDynamicsListVO.setPageHelper(pageHelper);
        return communicateDynamicsListVO;
    }


    @Override
    public FormDataDetailVO getDetail(FormDataDetailDTO formDataDetailDTO) throws XbbException {
        // if (!checkDataPermission(formDataDetailDTO)) {
        //     throw new XbbException(SystemErrorCodeEnum.API_ERROR_100017);
        // }
        if (!checkData(formDataDetailDTO)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        if (Objects.equals(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode(), formDataDetailDTO.getBusinessType())) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, formDataDetailDTO.getCorpid());
            params.put(StringConstant.ID, formDataDetailDTO.getDataId());
            params.put("logType", BasicConstant.ZERO);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<CustomerCommunicateEntityExt> customerCommunicateModelEntitys = customerCommunicateModel.findEntitys(params);
            if (CollectionsUtil.isEmpty(customerCommunicateModelEntitys)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            CustomerCommunicateEntityExt customerCommunicateEntityExt = customerCommunicateModelEntitys.get(0);
            DynamicFormDataDetailVO dynamicFormDataDetailVO = new DynamicFormDataDetailVO();
            dynamicFormDataDetailVO.setPaasFormDataEntityExt(customerCommunicateEntityExt);
            return dynamicFormDataDetailVO;
        }else {
            return paasFormDataService.getDetail(formDataDetailDTO);
        }
    }

    @Override
    public CommunicateDynamicsListVO getSimpleDynamicList(DynamicListDTO dynamicListDTO) throws XbbException {
        String corpid = dynamicListDTO.getCorpid();
        Integer page = dynamicListDTO.getPage() == null ? 1 : dynamicListDTO.getPage();
        Integer pageSize = dynamicListDTO.getPageSize() == null ? 10 : dynamicListDTO.getPageSize();
        Integer businessType = dynamicListDTO.getBusinessType();
        Long parentId = dynamicListDTO.getParentId();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("dataId", parentId);
        param.put(StringConstant.DEL, 0);
        param.put(StringConstant.ORDER_BY, "add_time desc");
        param.put("start", (page - 1) * pageSize);
        param.put("pageSize", pageSize);

        List<SimpleDynamicEntity> simpleDynamicEntityList = simpleDynamicModel.findEntitys(param);

        List<CustomerDynamicsVO> competitorDynamicsVOList = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(simpleDynamicEntityList)){
            competitorDynamicsVOList = simpleDynamicEntityList.stream().map(dynamic -> {
                CustomerDynamicsVO customerDynamicsVO = new CustomerDynamicsVO();
                customerDynamicsVO.setMemo(dynamic.getMemo());
                customerDynamicsVO.setCommunicateTime(dynamic.getAddTime());
                customerDynamicsVO.setAddTime(dynamic.getAddTime());
                JSONObject communicateBusiness = new JSONObject();
                //封装穿透信息
                Long refId = dynamic.getRefId();
                if (Objects.nonNull(refId) && refId != 0L && !(Objects.equals(businessType,dynamic.getRefBusinessType()) && Objects.equals(parentId,refId))) {
                    JSONObject entityObj = new JSONObject();
                    int refBusinessType = dynamic.getRefBusinessType();
                    Integer businessType4Distributor = XbbRefTypeEnum.transferBusinessType4Distributor(refBusinessType, dynamicListDTO.getDistributorMark());
                    Integer saasMark = Objects.equals(refBusinessType, BasicConstant.ZERO) ? SaasMarkEnum.PAAS.getCode() : SaasMarkEnum.SAAS.getCode();
                    String bussinessName = Objects.equals(refBusinessType,BasicConstant.ZERO) ? I18nMessageUtil.getMessage(StringConstant.LINK_DATA) : dynamicHelp.getTemplateName(businessType4Distributor,refId,saasMark,corpid);
                    entityObj.put("dataId",refId);
                    entityObj.put("businessType",businessType4Distributor);
                    entityObj.put("saasMark",saasMark);

                    communicateBusiness.put("entity",entityObj);
                    communicateBusiness.put("businessName",bussinessName);
                    communicateBusiness.put("name", StringUtil.isNotEmpty(dynamic.getRefName()) ? dynamicHelp.getRealRefName(corpid,refId,refBusinessType,dynamic.getRefName()) : "--");
                    customerDynamicsVO.setCommunicateBusiness(communicateBusiness);
                }
                return customerDynamicsVO;
            }).collect(Collectors.toList());
        }


        CommunicateDynamicsListVO communicateDynamicsListVO = new CommunicateDynamicsListVO();
        // 设置分页数据
        param.remove("start");
        param.remove("pageSize");
        param.remove(StringConstant.ORDER_BY);
        PageHelper pageHelper = PageHelperUtil.initPageHelper(simpleDynamicModel.getEntitysCount(param), page, pageSize, pageSize);
        communicateDynamicsListVO.setList(competitorDynamicsVOList);
        communicateDynamicsListVO.setPageHelper(pageHelper);
        return communicateDynamicsListVO;
    }

    /**
     * 当前逻辑仅校验paas的表单数据是否存在
     * @param formDataDetailDTO
     * @return
     */
    private boolean checkData(FormDataDetailDTO formDataDetailDTO) {
        if (!Objects.equals(SaasMarkEnum.SAAS.getCode(), formDataDetailDTO.getSaasMark())) {
            List<PaasFormDataEntity> entitysByIds = paasFormDataModel.findEntitysByIds(Collections.singletonList(formDataDetailDTO.getDataId()), formDataDetailDTO.getCorpid(), DelEnum.NORMAL.getDel());
            return CollectionsUtil.isNotEmpty(entitysByIds);
        }
        return true;
    }

    /**
     * saas权限校验现有入口： com.xbongbong.saas.help.SaasDetailPermissionHelp#checkPermission
     * @param formDataDetailDTO
     * @return
     * @throws XbbException
     */
    private boolean checkDataPermission(FormDataDetailDTO formDataDetailDTO) throws XbbException {
        UserVO userVO = formDataDetailDTO.getLoginUser();
        Integer businessType = formDataDetailDTO.getBusinessType();

        if (userVO.isAdminOrBoss()) {
            return true;
        }

        // 排除paas校验
        String ownerIdText = getOwnerIdText(businessType);
        if (Objects.isNull(formDataDetailDTO.getSaasMark()) || Objects.equals(SaasMarkEnum.PAAS.getCode(), formDataDetailDTO.getSaasMark())) {
            // ownerIdText = "ownerId";
            return true;
        }
        if (StringUtil.isEmpty(ownerIdText)) {
            return true;
        }

        Long dataId = formDataDetailDTO.getDataId();
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        // 角色下面对应有数据权限
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, businessType, null);
        if (Objects.equals(dataPermission, DataPermissionEnum.ALL.getCode())) {
            return true;
        }

        List<String> userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userVO.getUserId(), userVO.getCorpid(), BasicConstant.ZERO, false);
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.getByCode(businessType);
        BoolQueryBuilder boolQueryBuilder = permissionQuery(userVO.getCorpid(), dataId, ownerIdText, userIdIn, businessType);
        long count = paasEsModel.count(boolQueryBuilder, indexTypeEnum);
        return count > 0L;
        // ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(indexTypeEnum, boolQueryBuilder, null);
        // return StringUtil.toInt(elasticAggsPojo.getTotal(), 0) > 0;
    }

    private BoolQueryBuilder permissionQuery(String corpid, Long dataId, String ownerIdText, List<String> userIds, Integer businessType) {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DATA_ID, dataId));
        boolQueryBuilder.filter(termsQuery(ownerIdText + ".keyword", userIds));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        // boolQueryBuilder.filter(termsQuery(StringConstant.FLOW_STATUS, Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        if (Objects.equals(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode(), businessType)) {
            boolQueryBuilder.filter(termQuery("logType", 0));
        }
        return boolQueryBuilder;
    }

    /**
     * 参考： com.xbongbong.saas.help.SaasDetailPermissionHelp#getOwnerId
     * @param businessType
     * @return
     */
    private String getOwnerIdText(Integer businessType) {
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum) {
            case CUSTOMER_COMMUNICATE:
                return StringConstant.CREATOR_ID;
            default:
                break;
        }
        return null;
    }

    /**
     *
     * date: 2022/5/20 3:31 下午
     * @author yingjf
     * @param businessType: 业务类型
     */
    private String getQueryAttr(Integer businessType) {
        String queryAttr = null;
        if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
            queryAttr = "customerId";
        } else if (Objects.equals(businessType, XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())) {
            queryAttr = "opportunityId";
        } else if (Objects.equals(businessType, XbbRefTypeEnum.CONTACT.getCode())) {
            queryAttr = "contactId";
        } else if (Objects.equals(businessType, XbbRefTypeEnum.CONTRACT.getCode())) {
            queryAttr = "contractId";
        }else if (Objects.equals(businessType,XbbRefTypeEnum.COMPETITOR.getCode())){
            queryAttr = "dataId";
        }
        return queryAttr;
    }

}
